home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / sprites.zip / SPRITES.PAS < prev    next >
Pascal/Delphi Source File  |  1991-04-15  |  15KB  |  503 lines

  1. unit Sprites;
  2. { Basically a simple and effective spriteengine for use with Turbo }
  3. { Pascal 6.0. (Does not require the GRAPH unit..)                  }
  4. {                                                                  }
  5. { Designed for use with MCGA, VGA and compatibles. Works in mode   }
  6. { mode $13 (320x200 with 256 simultaneously colours.               }
  7. {                                                                  }
  8. { Written by:                                                      }
  9. {            Marius Kjeldahl                                       }
  10. {            Stud. post 104                                        }
  11. {            N-7034 Trondheim - NTH                                }
  12. {            Norway                                                }
  13. {            Ph. +47 7 58 91 11                                    }
  14. {            e-mail: mariusk@lise.unit.no                          }
  15. {                    (at NTH - Norwegian Institute of Technology ) }
  16. {                    (dept. of Business and Information Technolgy) }
  17. {                                                                  }
  18. { These routines are being distributed as shareware. To be used in,}
  19. { or as part of any commercial product, you have to become a       }
  20. { registered user. As a registered user you will receive upgrades  }
  21. { and rights to distribute these routines with your products.      }
  22. { To become a registered user, you will have to send a letter with }
  23. { who you are and what product(s) will use these routines and      }
  24. { pay US$39 to the author's VISA, 4925 1730 1779 0386 or enclose   }
  25. { check or money.                                                  }
  26. {                                                                  }
  27. { If you have any suggestions or comments please do not hesitate   }
  28. { to contact me. Have fun...                                       }
  29. {                                                                  }
  30. { Future plans for enhancements: interrupt driven, faster rep      }
  31. { movsw for sprites, built in animation..                          }
  32.  
  33. interface
  34. uses
  35.   Dos;
  36. const
  37.   MaxSprites = 14; { Maximum number of sprites activated simultaneously }
  38.   MaxDim = 25*25;  { Dimensions of largest sprite to be used (x*y)      }
  39. type
  40.   ScreenTypePointer = ^ScreenType;       { Pointer to a virtual screen  }
  41.   ScreenType = array [1..64000] of byte; { Array to hold virtual screen }
  42.   SpriteType = record                    { Misc. sprite data            }
  43.                  oldx, oldy,             { - old location               }
  44.                  x, y : integer;         { - current location           }
  45.                  w, h : byte;            { - width and height           }
  46.                  SpriteData,             { - spriteimage                }
  47.                  Buffer : array [0..MaxDim-1] of byte; { spritebackgr.  }
  48.                  Active : boolean;       { - currently active           }
  49.                  ix, iy : integer;       { - sprite increment           }
  50.                                          {   (not currently used)       }
  51.                end;
  52. var
  53.   Sprite : array [1..MaxSprites] of SpriteType; { Array of sprites      }
  54.   Virtual_Screen : ScreenTypePointer;    { Pointer to virtual screen    }
  55.  
  56.   procedure DrawSprites;
  57.   { Saves background and draws all currently active sprites at their    }
  58.   { current location.                                                   }
  59.  
  60.   procedure LoadSprite (Num : byte; FileName : string);
  61.   { Loads spritedata from ordinary text file. Examine the .SPR files    }
  62.   { for further details. Use .CEL files instead if you've have          }
  63.   { purchased AutoDesk Animator...                                      }
  64.  
  65.   procedure SetMode (Mode : word);
  66.   { Sets screen mode. Use $13 for use with sprites                      }
  67.  
  68.   procedure ShowVirtualScreen ;
  69.   { Copies the VirtualScreen to the users screen. Any changes done with }
  70.   { the sprites and/or their position will NOT be visible until this    }
  71.   { routine has been called!                                            }
  72.  
  73.   procedure LoadCOL (FileName : string);
  74.   { Loads a file containing the palette desc. of the 256 colours and    }
  75.   { programs the VGA/MCGA to use these palette. It uses AutoDesk        }
  76.   { Animators file format - so you can use Animator to select colors and}
  77.   { then save the palette in Animators ordinary .COL file.              }
  78.   { For those without Animator (you should not be..) the file format is }
  79.   { simple. Each colour (from 0 to 255) has three bytes which containts }
  80.   { red, green and blue values. First in the file comes (usually)       }
  81.   { 0,0,0 - black and so on until the last colour.                      }
  82.  
  83.   procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  84.   { Directly loads a CEL to the location pointed to by ScrPtr.          }
  85.   { This routine uses AutoDesk Animators file format. This means you    }
  86.   { can use Animators excellent drawing tools to design you sprites and }
  87.   { save them in a ordinary .CEL file.                                  }
  88.   { For those without Animator; here is a short desc. of the format:    }
  89.   { The first 800 bytes is Animators header. It does include various    }
  90.   { information like it's own colours palette, width and height.        }
  91.   { However this version skips all that information and just reads the  }
  92.   { image data into the location pointed to by ScrPtr. Remember to      }
  93.   { set the sprites width and height too! (It is NOT read you of the    }
  94.   { .CEL file in this release..                                         }
  95.  
  96.   procedure DisableAllSprites;
  97.   { Disables all sprites. But this routine does not restore the screen  }
  98.   { image (compare with HideSprites..                                   }
  99.  
  100.   procedure HideSprites;
  101.   { Disables all sprites. Basically same as DisableAllSprites, but this }
  102.   { routine also recovers the "original" screen image.                  }
  103.  
  104.   procedure FillBox (x1, y1, x2, y2 : integer; b : byte);
  105.   { Draws a coloured box with upper left corner x1,y1 and lower right   }
  106.   { corner x2,y2.                                                       }
  107.  
  108.   procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer);
  109.   { "Stamps" a copy of any sprite at the chosen location x1,y1.         }
  110.   { Use this routine if you want to put the image there, but do not plan}
  111.   { to animate in anyway..                                              }
  112.  
  113.   procedure WaitForVerticalRetrace;
  114.   { Waits for vertical retrace. Will be used in further releases..      }
  115.  
  116. implementation
  117.  
  118. procedure CopySprite (var Sprite : SpriteType; x1, y1 : integer); assembler;
  119. label
  120.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  121.   asm
  122.     push  ds
  123.     push  es
  124.     lds   si,Sprite
  125.     mov   ax,x1     { ax = x }
  126.     mov   bx,y1     { bx = y }
  127. _Redraw:
  128.     push  ax
  129.     push  bx
  130.     mov   ax,word(Virtual_Screen+2)
  131.     mov   es,ax         { ES=A000h }
  132.     pop   bx            { ax = y }
  133.     mov   ax,320
  134.     mul   bx            { ax = y * 320 }
  135.     pop   bx            { ax = x }
  136.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  137.     mov   di,ax         { di = skjermadr. }
  138.     mov   dl,[si+9]     { dl = height of sprite }
  139.     xor   ch,ch
  140.     mov   cl,[si+8]     { cx = width of sprite }
  141.     add   si,10         { si = start of spritedata }
  142.     cld
  143. _DrawLoop:
  144.     push  di            { store y adr. for later }
  145.     push  cx            { store width }
  146. _LineLoop:
  147.     mov   bl,byte ptr [si]
  148.     or    bl,bl
  149.     jnz   _Store
  150. _NoPaint:
  151.     inc    si
  152.     inc    di
  153.     loop   _LineLoop
  154.     jmp    _NextLine
  155. _Store:
  156. {    test   byte ptr [es:di],1
  157.     jz     _NoPaint}
  158.     movsb
  159.     loop  _LineLoop
  160. _NextLine:
  161.     pop   cx
  162.     pop   di
  163.     dec   dl
  164.     jz    _Exit
  165.     add   di,320        { di = next line of sprite }
  166.     jmp   _DrawLoop
  167. _Exit:
  168.     pop   es
  169.     pop   ds
  170.   end;
  171.  
  172. procedure DrawSprite (var Sprite : SpriteType); assembler;
  173. label
  174.   _Redraw, _DrawLoop, _Exit, _LineLoop, _NextLine, _Store, _NoPaint;
  175.   asm
  176.     push  ds
  177.     push  es
  178.     lds   si,Sprite
  179.     mov   ax,[si+4]     { ax = x }
  180.     mov   bx,[si+6]     { bx = y }
  181.     {cmp   ax,[si]        if x <> oldx then _Redraw
  182.     jne   _Redraw
  183.     cmp   bx,[si+2]
  184.     je    _Exit}         { if (x=oldx) and (y=oldy) then exit }
  185. _Redraw:
  186.     mov   [si],ax       { oldx = x }
  187.     mov   [si+2],bx     { oldy = y }
  188.     push  ax
  189.     push  bx
  190.     mov   ax,word(Virtual_Screen+2)
  191.     mov   es,ax         { ES=A000h }
  192.     pop   bx            { ax = y }
  193.     mov   ax,320
  194.     mul   bx            { ax = y * 320 }
  195.     pop   bx            { ax = x }
  196.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  197.     mov   di,ax         { di = skjermadr. }
  198.     mov   dl,[si+9]     { dl = height of sprite }
  199.     xor   ch,ch
  200.     mov   cl,[si+8]     { cx = width of sprite }
  201.     add   si,10         { si = start of spritedata }
  202.     cld
  203. _DrawLoop:
  204.     push  di            { store y adr. for later }
  205.     push  cx            { store width }
  206. _LineLoop:
  207.     mov   bl,byte ptr [si]
  208.     or    bl,bl
  209.     jnz   _Store
  210. _NoPaint:
  211.     inc    si
  212.     inc    di
  213.     loop   _LineLoop
  214.     jmp    _NextLine
  215. _Store:
  216. {    test   byte ptr [es:di],1
  217.     jz     _NoPaint}
  218.     movsb
  219.     loop  _LineLoop
  220. _NextLine:
  221.     pop   cx
  222.     pop   di
  223.     dec   dl
  224.     jz    _Exit
  225.     add   di,320        { di = next line of sprite }
  226.     jmp   _DrawLoop
  227. _Exit:
  228.     pop   es
  229.     pop   ds
  230.   end;
  231.  
  232. procedure SaveSpriteBackground (var Sprite : Spritetype); assembler;
  233. label
  234.   _Redraw, _DrawLoop, _Exit;
  235.   asm
  236.     push  ds
  237.     push  es
  238.     les   di,Sprite
  239.     mov   ax,es:[di+4]     { ax = x }
  240.     mov   bx,es:[di+6]     { bx = y }
  241.     push  ax
  242.     push  bx
  243.     mov   ax,word(Virtual_Screen+2)
  244.     mov   ds,ax         { DS=A000h }
  245.     pop   bx            { bx = y }
  246.     mov   ax,320
  247.     mul   bx            { ax = y * 320 }
  248.     pop   bx            { bx = x }
  249.     add   ax,bx         { ax = ax + bx dvs. skjermadr.. }
  250.     mov   si,ax         { si = skjermadr. }
  251.     mov   dl,es:[di+9]     { dl = height of sprite }
  252.     xor   ch,ch
  253.     mov   cl,es:[di+8]     { cx = width of sprite }
  254.     add   di,10+MaxDim  { di = start of screenbuffer }
  255.     cld
  256. _DrawLoop:
  257.     push  si            { store y adr. for later }
  258.     push  cx            { store width }
  259.     rep   movsb
  260.     pop   cx
  261.     pop   si
  262.     dec   dl
  263.     jz    _Exit
  264.     add   si,320        { di = next line of sprite }
  265.     jmp   _DrawLoop
  266. _Exit:
  267.     pop   es
  268.     pop   ds
  269.   end;
  270.  
  271. procedure FillBox (x1, y1, x2, y2 : integer; b : byte); assembler;
  272. label
  273.   _l1;
  274. asm
  275.   push  ds
  276.   push  es
  277.   mov   ax,word(Virtual_Screen+2)
  278.   mov   es,ax
  279.   mov   ax,y1
  280.   mov   bx,320
  281.   mul   bx
  282.   mov   di,ax
  283.   add   di,x1
  284.   mov   ax,y1
  285.   mov   dx,y2
  286.   sub   dx,ax
  287.   inc   dx
  288.  
  289.   mov   ax,x1
  290.   mov   cx,x2
  291.   sub   cx,ax { cx contains number of bytes across }
  292.   inc   cx
  293.   mov   al,b
  294.   cld
  295. _l1:
  296.   push  di
  297.   push  cx
  298.   rep   stosb
  299.   pop   cx
  300.   pop   di
  301.   add   di,320
  302.   dec   dx
  303.   jnz   _l1
  304.   pop   es
  305.   pop   ds
  306. end;
  307.  
  308.  
  309. procedure RestoreSpriteBackground (var Sprite : Spritetype); assembler;
  310. label
  311.   _Redraw, _DrawLoop, _Exit, _LineLoop;
  312.   asm
  313.     push  ds
  314.     push  es
  315.     lds   si,Sprite
  316.     mov   ax,[si]     { ax = x }
  317.     mov   bx,[si+2]     { bx = y }
  318.     push  ax
  319.     push  bx
  320.     mov   ax,word(Virtual_Screen+2)
  321.     mov   es,ax         { ES=A000h }
  322.     pop   bx            { ax = y }
  323.     mov   ax,320
  324.     mul   bx            { ax = y * 320 }
  325.     pop   bx            { ax = x }
  326.     add   ax,bx         { bx = bx + ax dvs. skjermadr.. }
  327.     mov   di,ax         { di = skjermadr. }
  328.     mov   dl,[si+9]     { dl = height of sprite }
  329.     xor   ch,ch
  330.     mov   cl,[si+8]     { cx = width of sprite }
  331.     add   si,10+MaxDim         { si = start of spritedata }
  332.     cld
  333. _DrawLoop:
  334.     push  di            { store y adr. for later }
  335.     push  cx            { store width }
  336.     rep   movsb
  337.     pop   cx
  338.     pop   di
  339.     dec   dl
  340.     jz    _Exit
  341.     add   di,320        { di = next line of sprite }
  342.     jmp   _DrawLoop
  343. _Exit:
  344.     pop   es
  345.     pop   ds
  346.   end;
  347.  
  348. procedure DrawSprites;
  349. var
  350.   I : byte;
  351. begin
  352.   for I := MaxSprites downto 1 do
  353.     if (Sprite[I].Active) and (Sprite [I].oldx <> -1) then
  354.       RestoreSpriteBackground (Sprite [I]);
  355.   for I := 1 to MaxSprites do begin
  356.     if Sprite [I].Active then begin
  357.       SaveSpriteBackground (Sprite [I]);
  358.       DrawSprite (Sprite [I]);
  359.     end;
  360.   end;
  361. end;
  362.  
  363. procedure HideSprites;
  364. var
  365.   I : byte;
  366. begin
  367.   for I := MaxSprites downto 1 do
  368.     if (Sprite [I].oldx <> -1) then begin
  369.       RestoreSpriteBackground (Sprite [I]);
  370.       Sprite [I].oldx := -1;
  371.     end;
  372. end;
  373.  
  374. procedure SetMode (Mode : word);
  375. begin
  376.   asm
  377.     mov ax,Mode;
  378.     int 10h
  379.   end;
  380. end;
  381.  
  382. procedure LoadSprite (Num : byte; FileName : string);
  383. var
  384.   Fil : text;
  385.   fx, fy : word;
  386. begin
  387.   assign (Fil, FileName);
  388.   reset (Fil);
  389.   fillchar (Sprite [Num], sizeof (Sprite[1]), 0);
  390.   with Sprite [Num] do begin
  391.     oldx := integer ($FFFF);
  392.     readln (Fil, w, h);          {integer-32768}
  393.     for fy := 1 to h do begin
  394.       for fx := 1 to w do
  395.         read (Fil, SpriteData [pred (fy) * w + pred (fx)]);
  396.       readln (fil);
  397.     end;
  398.   end;
  399.   close (Fil);
  400. end;
  401.  
  402. procedure LoadCOL (FileName : string);
  403. type
  404.   DACType = array [0..255] of record
  405.                                 R, G, B : byte;
  406.                               end;
  407. var
  408.   DAC : DACType;
  409.   Fil : file of DACType;
  410.   I : integer;
  411.   Regs : Registers;
  412. begin
  413.   assign (Fil, FileName);
  414.   reset (Fil);
  415.   read (Fil, DAC);
  416.   close (Fil);
  417.   for I := 0 to 255 do begin
  418.     with Regs do begin
  419.       AX := $1010;
  420.       BX := I;
  421.       DH := DAC [I].R;
  422.       CH := DAC [I].G;
  423.       CL := DAC [I].B;
  424.     end;
  425.     Intr ($10, Regs);
  426.   end;
  427. end;
  428.  
  429. procedure WaitForVerticalRetrace; assembler;
  430. label
  431.   l1, l2;
  432. asm
  433.     cli
  434.     mov dx,3DAh
  435. l1:
  436.     in al,dx
  437.     and al,08h
  438.     jnz l1
  439. l2:
  440.     in al,dx
  441.     and al,08h
  442.     jz  l2
  443.     sti
  444. end;
  445.  
  446. procedure ShowVirtualScreen; assembler;
  447.     asm
  448.       push ds
  449.       push es
  450.       xor  si,si
  451.       xor  di,di
  452.       cld
  453.       mov  ax,word(Virtual_Screen+2)
  454.       mov  ds,ax
  455.       mov  ax,0A000h
  456.       mov  es,ax
  457.       mov  cx,7D00h
  458.       rep  movsw
  459.       pop  es
  460.       pop  ds
  461.     end;
  462.  
  463. procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  464. var
  465.   Fil : file;
  466.   Buf : array [1..1024] of byte;
  467.   BlocksRead, Count : word;
  468. begin
  469.   assign (Fil, FileName);
  470.   reset (Fil, 1);
  471.   BlockRead (Fil, Buf, 800);
  472.   Count := 0; BlocksRead := $FFFF;
  473.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  474.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  475.     Count := Count + 1024;
  476.   end;
  477.   close (Fil);
  478. end;
  479.  
  480. procedure DisableAllSprites;
  481. var
  482.   I : integer;
  483. begin
  484.   for I := 1 to MaxSprites do
  485.     with Sprite [I] do begin
  486.       OldX := -1;
  487.       Active := FALSE;
  488.     end;
  489. end;
  490.  
  491. var
  492.   Dum : ^byte;
  493. begin
  494.   DisableAllSprites;
  495.   repeat
  496.     new (Virtual_Screen);
  497.     if ofs (Virtual_Screen^) <> 0 then begin
  498.       dispose (Virtual_Screen);
  499.       new (Dum);
  500.     end;
  501.   until ofs (Virtual_Screen^) = 0;
  502. end.
  503.